/*
* ============================================================================
*  Name     : GV60Config.cpp
*  Part of  : GV60
*  Copyright: Wipo Software
* ============================================================================
*/

#include <e32base.h>
#include <f32file.h>
#include "GV60Config.h"
#include "Logger.h"

#define XOR_KEY    'M'

_LIT(KSettingsFileName, "GV60.cfg");


CGV60Configuration::CGV60Configuration()
{
  ResetValues();
}

CGV60Configuration::~CGV60Configuration()
{
  // Nothing to do
}

void CGV60Configuration::ResetValues()
{
  m_iValues.iUsername.Zero();
  m_iValues.iPassword.Zero();
  m_iValues.bInitialSync = EFalse;
}

TBool CGV60Configuration::ReadFromFile()
{
  DEBUG1("ReadConfig");
  
  TBool bRet = EFalse;
  
  RFs iFileSession;
  if (KErrNone == iFileSession.Connect())
  {
    if (KErrNone == iFileSession.SetSessionToPrivate(EDriveC))
    {
      TFileName iFileName;
      iFileSession.PrivatePath(iFileName);
      iFileName.Append(KSettingsFileName);
      
      RFile iFile;
      if (KErrNone == iFile.Open(iFileSession, iFileName, EFileRead))
      {
        SETTINGS_BUF* pSettingsBuf = new SETTINGS_BUF();
        if (pSettingsBuf)
        {
          TBool bError = EFalse;

          // Store original length and zero the buffer
          TInt iOrigLen = pSettingsBuf->Length();
          pSettingsBuf->Zero();
          
          // Read file in chunks
          while (pSettingsBuf->Length() < iOrigLen)
          {
            TBuf8<50> iReadChunk;
            TInt iReadErr = iFile.Read(iReadChunk);
            if (iReadErr != KErrNone)
            {
              bError = ETrue;
              break;
            }
            if (iReadChunk.Length() == 0)
            {
              // End of file to be read
              break;
            }
            else if (iReadChunk.Length() > 0 && pSettingsBuf->Length() + iReadChunk.Length() <= iOrigLen)
            {
              pSettingsBuf->Append(iReadChunk);
            }
            else
            {
              bError = ETrue;
              break;
            }
          }
          
          // Check total length
          if (pSettingsBuf->Length() != iOrigLen)
          {
            DEBUG1("ReadConfig - Invalid file length");
            bError = ETrue;
          }
            
          // Execute XOR
          Xor(*pSettingsBuf);

          // Verify parity
          if (CalculateParity((*pSettingsBuf)()) != (*pSettingsBuf)().iParity)
          {
            DEBUG1("ReadConfig - Invalid parity");
            bError = ETrue;
          }
          
          // Assign values
          if (!bError)
          {
            m_iValues.iUsername.Copy((*pSettingsBuf)().iUsername);
            m_iValues.iPassword.Copy((*pSettingsBuf)().iPassword);

            m_iValues.bInitialSync = (*pSettingsBuf)().bInitialSync;
            m_iValues.iParity      = (*pSettingsBuf)().iParity;
          
            DEBUG2("ReadConfig - Username len = ", m_iValues.iUsername.Length());
            DEBUG2("ReadConfig - Password len = ", m_iValues.iPassword.Length());
            DEBUG2("ReadConfig - Initial sync = ", m_iValues.bInitialSync);
            
            bRet = ETrue;
          }
          else
          {
            DEBUG1("ReadConfig - Error!");
          }
          
          delete pSettingsBuf;
        }
        iFile.Close();        
      }
    }
    iFileSession.Close();
  }
  
  return bRet;
}

TBool CGV60Configuration::WriteToFile()
{
  DEBUG1("WriteConfig");

  TBool bRet = EFalse;
  
  RFs iFileSession;
  if (KErrNone == iFileSession.Connect())
  {
    if (KErrNone == iFileSession.CreatePrivatePath(EDriveC))
    {
      if (KErrNone == iFileSession.SetSessionToPrivate(EDriveC))
      {        
        TFileName iFileName;
        iFileSession.PrivatePath(iFileName);
        iFileName.Append(KSettingsFileName);
        
        RFile iFile;
        if (KErrNone == iFile.Replace(iFileSession, iFileName, EFileWrite))
        {
          SETTINGS_BUF* pSettingsBuf = new SETTINGS_BUF();
          if (pSettingsBuf)
          {
            (*pSettingsBuf)().iUsername.Copy(m_iValues.iUsername);
            (*pSettingsBuf)().iPassword.Copy(m_iValues.iPassword);
            
            (*pSettingsBuf)().bInitialSync = m_iValues.bInitialSync;
            (*pSettingsBuf)().iParity      = CalculateParity(m_iValues);
            
            // Execute XOR
            Xor(*pSettingsBuf);
            
            if (KErrNone == iFile.Write((*pSettingsBuf)))
            {
              DEBUG1("WriteConfig ok");
              bRet = ETrue;
            }

            iFile.Flush();
            
            delete pSettingsBuf;
          }
          iFile.Close();
        }
      }
    }
    iFileSession.Close();
  }

  return bRet;
}

TInt CGV60Configuration::CalculateParity(const TSettingsValues& iValues)
{
  TInt i;
  TInt iResult = 0;
  
  iResult = (iResult + (TInt)iValues.bInitialSync) % 255;

  for (i = 0; i < iValues.iUsername.Length(); i++)
  {
    iResult = (iResult + (TInt)iValues.iUsername[i]) % 255;
  }

  for (i = 0; i < iValues.iPassword.Length(); i++)
  {
    iResult = (iResult + (TInt)iValues.iPassword[i]) % 255;
  }

  return iResult;
}

void CGV60Configuration::Xor(TDes8& iString)
{
  for (TInt i = 0; i < iString.Length(); i++)
  {
    iString[i] = iString[i] ^ XOR_KEY;
  }
}
